package niu.toy.spring.mvc.impl;

import niu.toy.spring.ioc.annotation.Nullable;
import niu.toy.spring.mvc.View;


import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.util.*;


public abstract class AbstractView implements View {
    private static final Logger logger = LoggerFactory.getLogger(AbstractView.class);

    private String url;
    public String getUrl() {
        return url;
    }
    public void setUrl(String url) {
        this.url = url;
    }

    @Override
    public void render(@Nullable Map<String, Object> model, HttpServletRequest request,
                       HttpServletResponse response) throws Exception {

        if (logger.isTraceEnabled()) {
            logger.trace("Rendering view with url '" + this.url + "' with model " + model);
        }
        renderMergedOutputModel(model, request, response);
    }

    /**
     * 实际视图渲染由子类实，
     * @param model 传递给页面的值
     * @param request current HTTP request
     * @param response current HTTP response
     * @throws Exception if rendering failed
     */
    protected abstract void renderMergedOutputModel(
            Map<String, Object> model, HttpServletRequest request, HttpServletResponse response) throws Exception;


    protected void exposeModelAsRequestAttributes(Map<String, Object> model,
                                                  HttpServletRequest request) throws Exception {
        model.forEach((modelName, modelValue) -> {
            if (modelValue != null) {
                request.setAttribute(modelName, modelValue);
                if (logger.isDebugEnabled()) {
                    logger.debug("Added model object '" + modelName + "' of type [" + modelValue.getClass().getName() +
                            "] to request in view with url '" + this.url + "'");
                }
            }
            else {
                request.removeAttribute(modelName);
                if (logger.isDebugEnabled()) {
                    logger.debug("Removed model object '" + modelName +
                            "' from request in view with url '" + this.url  + "'");
                }
            }
        });
    }

    @Override
    public String toString() {
        StringBuilder sb = new StringBuilder(getClass().getName());
        sb.append(": url '").append(this.url).append("'");
        return sb.toString();
    }

}
